﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PhoneBook.Filters;
using PhoneBook.Hubs;
using PhoneBook.Middlewares;
using PhoneBook.Models;
using PhoneBook.Service;
using Swashbuckle.AspNetCore.Swagger;

namespace PhoneBook
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            var connection = @"Server=(localdb)\mssqllocaldb;Database=EFGetStarted.AspNetCore.NewDb;Trusted_Connection=True;ConnectRetryCount=0";
            services.AddDbContext<BloggingContext>
                (options => options.UseSqlServer(connection));

            services.AddSwaggerGen(opt =>
            {
                opt.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "ToDo API",
                    Description = "A simple example ASP.NET Core Web API",
                    TermsOfService = "None",
                    Contact = new Contact
                    {
                        Name = "Shayne Boyer",
                        Email = string.Empty,
                        Url = "https://twitter.com/spboyer"
                    },
                    License = new License
                    {
                        Name = "Use under LICX",
                        Url = "https://example.com/license"
                    }
                });
                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                opt.IncludeXmlComments(xmlPath);
            });

            services.AddDbContext<TodoContext>(opt=> {
                opt.UseInMemoryDatabase("TodoList");
            });

            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });


            services.AddMvc(options => {
                options.Filters.Add(typeof(SimpleResourceFilterAttribute));
                options.Filters.Add(typeof(SimpleActionFilterAttribute));
                options.Filters.Add(typeof(SimpleExceptionFilterAttribute));
                options.Filters.Add(typeof(SimpleResultFilterAttribute));
            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            services.AddSignalR();

            services.AddSession();


            //配置authorrize
            services.AddAuthentication(b =>
            {
                b.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                b.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                b.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

            }).AddCookie(b =>{ 
                //登陆地址
                b.LoginPath = "/Account/Login2";
                //sid
                b.Cookie.Name = "My_SessionId";
                // b.Cookie.Domain = "shenniu.core.com";
                b.Cookie.Path = "/";
                b.Cookie.HttpOnly = true;
                b.Cookie.Expiration = new TimeSpan(0, 0, 30);
                b.ExpireTimeSpan = new TimeSpan(0, 0, 30);
            });

            services.AddAutoMapper(typeof(Startup));

            //循环依赖测试
            services.AddScoped<ClientUserService>();
            services.AddScoped<IAccountService, AccountService>();
            services.AddScoped<IUserService, UserService>();

        }



        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            //loggingBuilder.AddConsole();
            //loggingBuilder.AddDebug();
            
            //loggerFactory.AddNLog();
            //app.UseVisitLogger();
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            //app.UseSession();
            //app.Run( async(ctx) => 
            //{
            //    await ctx.Response.WriteAsync("hello wold");
            //});

            app.Use(async (ctx, next) =>
            {
                //await ctx.Response.WriteAsync("hello wold");
                await next();
            });

            app.Map("/test", MapTest);

            app.Map("/test2", lv1App => {
                lv1App.Map("/test3", lv11App => {
                    // /level1/level1.1
                    lv11App.Run(async (ctx) =>
                    {
                        await ctx.Response.WriteAsync("level1.1");
                    });
                });

                lv1App.Map("/test4", lv12App => {
                    // /level1/level1.2
                    lv12App.Run(async (ctx) =>
                    {
                        await ctx.Response.WriteAsync("level1.2");
                    });
                });
            });

            //app.MapWhen(context =>
            //{
            //    return context.Request.Query.ContainsKey("a");
            //}, MapTest);

            //app.UseMiddleware<HelloworldTooMiddleware>();

            //app.Use(async (context, next) =>
            //{
            //    await context.Response.WriteAsync("Hello World!1/n/r");
            //    await next();
            //    await context.Response.WriteAsync("Hello World!1后/n/r");
            //});

            //app.Use(async (context, next) =>
            //{
            //    await context.Response.WriteAsync("Hello World!2/n/r");
            //    await next();
            //    await context.Response.WriteAsync("Hello World!2后/n/r");
            //});

           // app.Run(async (ctx) =>
           //{
           //    await ctx.Response.WriteAsync("hello wold3/n/r");
           //});
            app.UseHttpsRedirection();
            app.UseDefaultFiles();
            app.UseStaticFiles();
            
            app.UseCookiePolicy();

            // Authenticate before the user accesses secure resources.
            app.UseAuthentication();

            app.UseSession();
            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger();

            // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), 
            // specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
                //c.RoutePrefix = string.Empty;
            });

            app.UseSignalR(routes=> {
                routes.MapHub<ChatHub>("/chatHub");
            });


            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

        private static void MapTest(IApplicationBuilder app)
        {
            app.Run(async context => {
                await context.Response.WriteAsync("Url is " + context.Request.PathBase.ToString());
            });
        }
    }
}
